package v1

import (
	"net/http"
	"strconv"
	"zhejianglab/gin-apiserver/model"
	"zhejianglab/gin-apiserver/model/request"

	"github.com/astaxie/beego/validation"
	"github.com/gin-gonic/gin"
)

// AddNewConfig create new Config
// @Produce  json
// @Tags Config
// @Param ConfigInfo body request.ConfigInfo true "request.ConfigInfo"
// @Success 201 {object} gin.H "{"code":201,"msg":"AddNewConfig successfully"}"
// @Failure 500 {object} gin.H "{"code":500,"msg":"AddNewConfig: Config name is invalid"}"
// @Router /api/v1/config/new [post]
func AddNewConfig(c *gin.Context) {

	var Config request.ConfigInfo
	_ = c.ShouldBindJSON(&Config)
	configInfo := model.ConfigInfo{
		AlgorithmName:          Config.AlgorithmName,
		Port:                   Config.Port,
		CameraID:               Config.CameraID,
		ConfidenceThreshold:    Config.ConfidenceThreshold,
		ProcessingFrameRate:    Config.ProcessingFrameRate,
		AlarmVideoTime:         Config.AlarmVideoTime,
		RegularAreaCoordinates: Config.RegularAreaCoordinates,
		SecurityOfficerColor:   Config.SecurityOfficerColor,
		FrameNumberForAlarm:    Config.FrameNumberForAlarm,
	}
	// todo 需要对参数进行校验
	model.AddNewConfig(configInfo)
	c.JSON(http.StatusCreated, gin.H{"status": http.StatusCreated, "message": "AddNewConfig successfully!", "data": Config.AlgorithmName})
}

// GetConfigWithAlgorithmName get Config info from db
// @Produce  json
// @Tags Config
// @Param algorithm_name path int64 true "algorithmName"
// @Success 200 {object} gin.H "{"code":200,"msg":"GetConfig successfully"}"
// @Failure 500 {object} gin.H "{"code":500,"msg":"GetConfig failed!"}"
// @Router /api/v1/config [get]
func GetConfigWithAlgorithmName(c *gin.Context) {

	algorithmName := c.Query("algorithmname")
	var err error
	if algorithmName == "" {
		data, err := model.GetAllConfigs()
		if err != nil {
			c.JSON(http.StatusInternalServerError, gin.H{"status": http.StatusInternalServerError, "message": err.Error()})
			return
		}
		c.JSON(http.StatusOK, gin.H{"status": http.StatusOK, "message": "GetConfig successfully!", "data": data})
		return
	}

	data, err := model.GetConfigWithAlgorithmName(algorithmName)
	if err != nil {
		c.JSON(http.StatusInternalServerError, gin.H{"status": http.StatusInternalServerError, "message": err.Error()})
		return
	}
	c.JSON(http.StatusOK, gin.H{"status": http.StatusOK, "message": "GetConfig successfully!", "data": data})
}

// UpdateConfig update Config info
// @Produce  json
// @Tags Config
// @Param ConfigInfo body request.ConfigInfo true "request.ConfigInfo"
// @Success 201 {object} gin.H "{"code":201,"msg":"UpdateConfig successfully"}"
// @Failure 500 {object} gin.H "{"code":500,"msg":"UpdateConfig: Config name is invalid"}"
// @Router /api/v1/config/{id} [put]
func UpdateConfig(c *gin.Context) {
	var err error
	data := make(map[string]interface{})
	id, err := strconv.Atoi(c.Param("id"))
	if err != nil {
		c.JSON(http.StatusInternalServerError, gin.H{"status": http.StatusInternalServerError, "message": err.Error()})
		return
	}

	var config request.ConfigInfo

	err = c.ShouldBindJSON(&config)
	if err != nil {
		c.JSON(http.StatusInternalServerError, gin.H{"status": http.StatusInternalServerError, "message": "UpdateConfig failed!" + err.Error()})
		return
	}
	if !model.ExistConfigByID(id) {
		c.JSON(http.StatusInternalServerError, gin.H{"status": http.StatusInternalServerError, "message": "Config id is not exists failed!"})
		return
	}

	if config.AlgorithmName != "" {
		data["algorithm_name"] = config.AlgorithmName
	}
	if config.CameraList != "" {
		data["camera_list"] = config.CameraList
	}
	if config.ConfigParams != "" {
		data["config_params"] = config.ConfigParams
	}
	if config.Port != 0 {
		data["port"] = config.Port
	}

	model.UpdateConfig(id, data)
	c.JSON(http.StatusOK, gin.H{"status": http.StatusOK, "message": "UpdateConfig successfully!", "data": data})
	return

}

// DeleteConfig delete Config info from db
// @Produce  json
// @Tags Config
// @Param id path int true "ID"
// @Success 200 {object} gin.H "{"code":200,"msg":"DeleteConfig successfully"}"
// @Failure 500 {object} gin.H "{"code":500,"msg":"DeleteConfig failed!"}"
// @Failure 500 {object} gin.H "{"code":500,"msg":"id is invalid!"}"
// @Router /api/v1/config/{id} [delete]
func DeleteConfig(c *gin.Context) {
	id, err := strconv.Atoi(c.Param("id"))
	if err != nil {
		c.JSON(http.StatusInternalServerError, gin.H{"status": http.StatusInternalServerError, "message": err.Error()})
		return
	}

	valid := validation.Validation{}
	valid.Min(id, 1, "id").Message("ID必须大于0")

	if !valid.HasErrors() {
		if model.ExistConfigByID(id) {
			model.DeleteConfig(id)
			c.JSON(http.StatusOK, gin.H{"status": http.StatusOK, "message": "DeleteConfig successfully!"})
		} else {
			c.JSON(http.StatusInternalServerError, gin.H{"status": http.StatusInternalServerError, "message": "DeleteConfig failed!"})
			return
		}
	} else {
		c.JSON(http.StatusInternalServerError, gin.H{"status": http.StatusInternalServerError, "message": "id is invalid!"})
		return
	}
}
